/**
 *
 */
package de.cbf.cam.dsa.rcp.model.persistence.xml.extension;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jface.preference.IPreferenceStore;

import de.cbf.cam.dsa.rcp.model.entities.CultureDSA;
import de.cbf.cam.dsa.rcp.model.entities.ProfessionDSA;
import de.cbf.cam.dsa.rcp.model.entities.RaceDSA;
import de.cbf.cam.dsa.rcp.model.entities.StructureData;
import de.cbf.cam.dsa.rcp.model.entities.items.CultureItemDSA;
import de.cbf.cam.dsa.rcp.model.entities.items.ItemForProfessionAlternatives;
import de.cbf.cam.dsa.rcp.model.entities.items.ProfessionItemDSA;
import de.cbf.cam.dsa.rcp.model.persistence.xml.act.ActivatorRCPModelPersistence;
import de.cbf.cam.dsa.rcp.model.persistence.xml.preferences.PreferenceConstants;
import de.cbf.cam.dsa.services.impl.rcp_provider.extension.interfaces.AbstractParameteredPersister;
import de.cbf.cam.dsa.services.impl.rcp_provider.extension.interfaces.IRCPPersisterCulture;
import de.cbf.cam.dsa.services.impl.rcp_provider.extension.interfaces.IRCPPersisterProfession;
import de.cbf.cam.dsa.services.impl.rcp_provider.extension.interfaces.IRCPPersisterRace;
import de.cbf.cam.dsa.services.impl.rcp_provider.extension.interfaces.IRCPPersisterStructure;
import de.cbf.util.CBFFileUtil;
import de.cbf.util.db.interfaces.exceptions.EntityLoadException;
import de.cbf.util.db.interfaces.exceptions.EntitySaveException;
import de.cbf.util.uuidheader.entities.UUIDHeader;
import de.cbf.util.uuidheader.interfaces.IUUIDHeader;
import de.cbf.util.xml.provider.EntityPersisterXML;

/**
 * @author salter
 *
 */
public class PersisterExtensionGatewayXML extends AbstractParameteredPersister implements
	IRCPPersisterRace,IRCPPersisterCulture,IRCPPersisterProfession,IRCPPersisterStructure{
	private static final Log logger = LogFactory.getLog(PersisterExtensionGatewayXML.class);

	public static final String PROPERTY_KEY_IMPORT_FILE 		= "xml.import.file.path";
	public static final String PROPERTY_KEY_IMPORT_DIRECTORY 	= "xml.import.directory.path";

	public static final String PROPERTY_KEY_EXPORT_FILE 		= "xml.export.file.path";
	public static final String PROPERTY_KEY_EXPORT_DIRECTORY 	= "xml.export.directory.path";

	public static final String PROPERTY_KEY_ARCHIVE_DIRECTORY 	= "xml.archive.directory.path";

	public static final String NAME = "RCP XML Persister";

	protected static final DateFormat TIME_FORMAT = new SimpleDateFormat("HHmm");
	protected static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");

	protected EntityPersisterXML persister;

	protected IPreferenceStore store;

	protected Map<UUID,File> importedRaceFiles	 		= new HashMap<UUID,File>();
	protected Map<UUID,File> importedCultureFiles 		= new HashMap<UUID,File>();
	protected Map<UUID,File> importedProfessionFiles	= new HashMap<UUID,File>();
	protected Map<UUID,File> importedStructureFiles 	= new HashMap<UUID,File>();

	protected String archiveDirNameRace 		= "Rasse";
	protected String archiveDirNameCulture 		= "Kultur";
	protected String archiveDirNameProfession 	= "Profession";
	protected String archiveDirNameStructure	= "Struktur";

	protected boolean uuidFilenameMode = false;

	/**
	 *
	 */
	public PersisterExtensionGatewayXML() {
		setName(NAME);
		store = ActivatorRCPModelPersistence.getDefault().getPreferenceStore();
		persister = new EntityPersisterXML();
		persister.setExtensionClassMap(buildExtensionClassMap());
		persister.setExtensionSeperator(".");
		persister.setAdditionalClasses(buildAdditionalClasses());
	}

	/**
	 * add some classes, that are not resolved automatically<br>
	 * in theory could use all classes here
	 * @return
	 */
	protected List<Class<?>> buildAdditionalClasses() {
		List<Class<?>> result = new ArrayList<Class<?>>();
		result.add(ItemForProfessionAlternatives.class);
		return result;
	}

	protected Map<String, Class<? extends IUUIDHeader>> buildExtensionClassMap() {
		Map<String,Class<? extends IUUIDHeader>> 	result = new HashMap<String, Class<? extends IUUIDHeader>>();
		String extensionRace 		= store.getString(PreferenceConstants.P_EXTENSION_RACE);
		String extensionCulture 	= store.getString(PreferenceConstants.P_EXTENSION_CULTURE);
		String extensionProfession 	= store.getString(PreferenceConstants.P_EXTENSION_PROFESSION);
		String extensionStructure	= store.getString(PreferenceConstants.P_EXTENSION_STRUCTURE);
		result.put(extensionRace		, RaceDSA.class);
		result.put(extensionCulture		, CultureItemDSA.class);
		result.put(extensionProfession	, ProfessionItemDSA.class);
		result.put(extensionStructure	, StructureData.class);
		return result;
	}

	protected String importParametersOK() {
		// check if files/directorys for import are available
		Object importDirObj = loadParameters.get(PROPERTY_KEY_IMPORT_DIRECTORY);
		Object importFileObj = loadParameters.get(PROPERTY_KEY_IMPORT_FILE);
		if( ! (importDirObj instanceof File) && ! (importFileObj instanceof File)){
			//if both are not set or no files
			String errorMsg = PROPERTY_KEY_IMPORT_DIRECTORY+" and "+PROPERTY_KEY_IMPORT_FILE+" not set correctly";
			logger.error(errorMsg);
			return errorMsg;
		}
		return "";
	}
	protected String exportParametersOK() {
		// check if files/directories for import are available
		// export file should be non existent, will warn if it is existing
		Object exportDirObj = saveParameters.get(PROPERTY_KEY_EXPORT_DIRECTORY);
		if(exportDirObj instanceof File){
			File exportDir = (File)exportDirObj;
			if( ! exportDir.exists()){
				logger.warn("export dir not existing: "+exportDir.getAbsolutePath()+" \n"+
						"creating it...");
				boolean success = exportDir.mkdirs();
				logger.debug("successfully created?: "+success);
			}
		}else{
			//if both are not set or no files
			String errorMsg = PROPERTY_KEY_EXPORT_DIRECTORY+" not set correctly";
			logger.error(errorMsg);
			return errorMsg;
		}
		Object exportFileObj = saveParameters.get(PROPERTY_KEY_EXPORT_FILE);
		if(exportFileObj instanceof File){
			File exportFile = (File)exportFileObj;
			if(exportFile.exists()){
				logger.warn("export file is existing(overwriting): "+exportFile.getAbsolutePath());
			}
			if( ! exportFile.canWrite()){
				logger.error("export file not writable: "+exportFile.getAbsolutePath());
			}
		}
		return "";
	}

	@Override
	public Collection<Object> getKnownLoadParameters() {
		List<Object> parameters = new ArrayList<Object>();
		return parameters;
	}


	@Override
	public Collection<Object> getKnownSaveParameters() {
		List<Object> parameters = new ArrayList<Object>();
		return parameters;
	}




	@Override
	public RaceDSA loadRace(UUID uuid) throws EntityLoadException {
		//check if file is specified
		Object importFilePathObj = loadParameters.get(PROPERTY_KEY_IMPORT_FILE);
		if (importFilePathObj instanceof File) {
			File file = (File) importFilePathObj;
			return importRaceFromFile(file);
		}
		Object importDirectoryObj = loadParameters.get(PROPERTY_KEY_IMPORT_DIRECTORY);
		if (importDirectoryObj instanceof File) {
			//load from specified directory and check uuid
			File directory = (File)importDirectoryObj;
			IUUIDHeader entity = loadEntityFromDirectoryByUUID(uuid, directory, RaceDSA.class, importedRaceFiles);
			if (entity instanceof RaceDSA) {
				RaceDSA race = (RaceDSA) entity;
				return race;
			}
		}
		throw new EntityLoadException("no race found for uuid "+uuid);
	}

	@Override
	public Collection<RaceDSA> loadAllRaces()throws EntityLoadException {
		Collection<RaceDSA> result = new ArrayList<RaceDSA>();
		//check if directory is set
		Object importDirectoryObj = loadParameters.get(PROPERTY_KEY_IMPORT_DIRECTORY);
		if (importDirectoryObj instanceof File) {
			File importDir = (File) importDirectoryObj;
			//really is directory, get all files and compare extensions to known
			Collection<IUUIDHeader> loaded = loadAllByClass(importDir, RaceDSA.class,importedRaceFiles);
			for (IUUIDHeader iuuidHeader : loaded) {
				if (iuuidHeader instanceof RaceDSA) {
					RaceDSA entiy = (RaceDSA) iuuidHeader;
					result.add(entiy);
				}
			}
		}else{
			throw new EntityLoadException(PROPERTY_KEY_IMPORT_DIRECTORY+ " not set correctly, cannot import all races from there");
		}
		return result;
	}

	protected RaceDSA importRaceFromFile(File file) throws EntityLoadException{
		IUUIDHeader entity = persister.importEntityFromXML(file, RaceDSA.class);
		if (entity instanceof RaceDSA) {
			RaceDSA race = (RaceDSA) entity;
			importedRaceFiles.put(race.getUuid(),file); //only if import was successful
			return race;
		}
		throw new EntityLoadException("Wrong entity type loaded: "+(entity != null?entity.getClass():null)+
				", expected: "+RaceDSA.class.getSimpleName());
	}

	public void tidyUpRaces(List<UUID> uuids){
		File archiveDir = null;
		Object obj = loadParameters.get(PROPERTY_KEY_ARCHIVE_DIRECTORY);
		if (obj instanceof File) {
			archiveDir = (File) obj;
		}
		for (UUID uuid : uuids) {
			File file = importedRaceFiles.get(uuid);
			if(file != null){
				if(archiveDir == null){
					//assume no archiving desired, so delete files from import folder
					file.delete();
				}else{
					//move files to archive
					//prepare archive directory
					File moveToDir = prepareArchiveDir(archiveDir,archiveDirNameRace);
					try {
						CBFFileUtil.copyFileToDir(file, moveToDir,TIME_FORMAT.format(new Date()));
						//delete original import file for move
						file.delete();
					} catch (IOException e) {
						logger.error(e);
					}
				}
			}else{
				logger.error("desired uuid not found in imported race files");
			}
		}
	}



	@Override
	public void saveRace(RaceDSA entity) throws EntitySaveException {
		saveEntity(entity);
	}

	@Override
	public CultureDSA loadCulture(UUID uuid) throws EntityLoadException {
		//check if file is specified
		Object importFilePathObj = loadParameters.get(PROPERTY_KEY_IMPORT_FILE);
		if (importFilePathObj instanceof File) {
			File file = (File) importFilePathObj;
			//load from specified file, uuid does not matter
			return importCultureFromFile(file);
		}
		Object importDirectoryOBj = loadParameters.get(PROPERTY_KEY_IMPORT_DIRECTORY);
		if (importDirectoryOBj instanceof File) {
			//load from specified directory and check uuid
			Collection<CultureDSA> all = loadAllCultures();
			for (CultureDSA entity : all) {
				if(entity.getUuid().toString().equals(uuid.toString())){
					return entity;
				}
			}
		}
		throw new EntityLoadException("no culture found for uuid "+uuid);
	}

	@Override
	public Collection<CultureDSA> loadAllCultures() throws EntityLoadException {
		Collection<CultureDSA> result = new ArrayList<CultureDSA>();
		//check if directory is set
		Object importDirectoryObj = loadParameters.get(PROPERTY_KEY_IMPORT_DIRECTORY);
		if (importDirectoryObj instanceof File) {
			File importDir = (File) importDirectoryObj;
			//really is directory, get all files and compare extensions to known
			Collection<IUUIDHeader> loaded = loadAllByClass(importDir, CultureItemDSA.class,importedCultureFiles);
			for (IUUIDHeader iuuidHeader : loaded) {
				if (iuuidHeader instanceof CultureDSA) {
					CultureDSA entiy = (CultureDSA) iuuidHeader;
					result.add(entiy);
				}
			}
		}else{
			throw new EntityLoadException(PROPERTY_KEY_IMPORT_DIRECTORY+ " not set correctly, cannot import all races from there");
		}
		return result;
	}

	protected CultureDSA importCultureFromFile(File file) throws EntityLoadException{
		IUUIDHeader entity = persister.importEntityFromXML(file, CultureDSA.class);
		if (entity instanceof CultureDSA) {
			CultureDSA culture = (CultureDSA) entity;
			importedCultureFiles.put(culture.getUuid(),file); //only if import was successful
			return culture;
		}
		throw new EntityLoadException("Wrong entity type loaded: "+(entity != null?entity.getClass():null)+
				", expected: "+CultureDSA.class.getSimpleName());
	}

	public void tidyUpCultures(List<UUID> uuids){
		File archiveDir = null;
		Object obj = loadParameters.get(PROPERTY_KEY_ARCHIVE_DIRECTORY);
		if (obj instanceof File) {
			archiveDir = (File) obj;
		}
		for (UUID uuid : uuids) {
			File file = importedCultureFiles.get(uuid);
			if(file != null){
				if(archiveDir == null){
					//assume no archiving desired, so delete files from import folder
					file.delete();
				}else{
					//move files to archive
					//prepare archive directory
					File moveToDir = prepareArchiveDir(archiveDir,archiveDirNameCulture);
					try {
						CBFFileUtil.copyFileToDir(file, moveToDir,TIME_FORMAT.format(new Date()));
						//delete original import file for move
						file.delete();
					} catch (IOException e) {
						logger.error(e);
					}
				}
			}else{
				logger.error("desired uuid not found in imported culture files");
			}
		}
	}

	@Override
	public void saveCulture(CultureDSA entity) throws EntitySaveException {
		saveEntity(entity);
	}



	@Override
	public ProfessionDSA loadProfession(UUID uuid) throws EntityLoadException {
		//check if file is specified
		Object importFilePathObj = loadParameters.get(PROPERTY_KEY_IMPORT_FILE);
		if (importFilePathObj instanceof File) {
			File file = (File) importFilePathObj;
			return importProfessionFromFile(file);
		}
		Object importDirectoryOBj = loadParameters.get(PROPERTY_KEY_IMPORT_DIRECTORY);
		if (importDirectoryOBj instanceof File) {
			//load from specified directory and check uuid
			Collection<ProfessionDSA> all = loadAllProfessions();
			for (ProfessionDSA entity : all) {
				if(entity.getUuid().toString().equals(uuid.toString())){
					return entity;
				}
			}
		}
		throw new EntityLoadException("no profession found for uuid "+uuid);
	}

	@Override
	public Collection<ProfessionDSA> loadAllProfessions() throws EntityLoadException {
		Collection<ProfessionDSA> result = new ArrayList<ProfessionDSA>();
		//check if directory is set
		Object importDirectoryObj = loadParameters.get(PROPERTY_KEY_IMPORT_DIRECTORY);
		if (importDirectoryObj instanceof File) {
			File importDir = (File) importDirectoryObj;
			//really is directory, get all files and compare extensions to known
			Collection<IUUIDHeader> loaded = loadAllByClass(importDir, ProfessionItemDSA.class,importedProfessionFiles);
			for (IUUIDHeader iuuidHeader : loaded) {
				if (iuuidHeader instanceof ProfessionDSA) {
					ProfessionDSA entiy = (ProfessionDSA) iuuidHeader;
					result.add(entiy);
				}
			}
		}else{
			throw new EntityLoadException(PROPERTY_KEY_IMPORT_DIRECTORY+ " not set correctly, cannot import all races from there");
		}
		return result;
	}

	protected ProfessionDSA importProfessionFromFile(File file) throws EntityLoadException{
		IUUIDHeader entity = persister.importEntityFromXML(file, ProfessionDSA.class);
		if (entity instanceof ProfessionDSA) {
			ProfessionDSA profession = (ProfessionDSA) entity;
			importedProfessionFiles.put(profession.getUuid(),file); //only if import was successful
			return profession;
		}
		throw new EntityLoadException("Wrong entity type loaded: "+(entity != null?entity.getClass():null)+
				", expected: "+ProfessionDSA.class.getSimpleName());
	}

	public void tidyUpProfessions(List<UUID> uuids){
		File archiveDir = null;
		Object obj = loadParameters.get(PROPERTY_KEY_ARCHIVE_DIRECTORY);
		if (obj instanceof File) {
			archiveDir = (File) obj;
		}
		for (UUID uuid : uuids) {
			File file = importedProfessionFiles.get(uuid);
			if(file != null){
				if(archiveDir == null){
					//assume no archiving desired, so delete files from import folder
					file.delete();
				}else{
					//move files to archive
					//prepare archive directory
					File moveToDir = prepareArchiveDir(archiveDir,archiveDirNameProfession);
					try {
						CBFFileUtil.copyFileToDir(file, moveToDir,TIME_FORMAT.format(new Date()));
						//delete original import file for move
						file.delete();
					} catch (IOException e) {
						logger.error(e);
					}
				}
			}else{
				logger.error("desired uuid not found in imported profession files");
			}
		}
	}

	@Override
	public void saveProfession(ProfessionDSA entity) throws EntitySaveException {
		saveEntity(entity);
	}

	@Override
	public StructureData loadStructure(UUID uuid) throws EntityLoadException {
		if(uuid == null){
			logger.warn("desired uuid is null, returning empty StructureData");
			return new StructureData();
		}
		//check if file is specified
		Object importFilePathObj = loadParameters.get(PROPERTY_KEY_IMPORT_FILE);
		if (importFilePathObj instanceof File) {
			File file = (File) importFilePathObj;
			//load from specified file, uuid does not matter
			return importStructureFromFile(file);
		}
		Object importDirectoryOBj = loadParameters.get(PROPERTY_KEY_IMPORT_DIRECTORY);
		if (importDirectoryOBj instanceof File) {
			//load from specified directory and check uuid
			Collection<StructureData> all = loadAllStructureData();
			if(all.size() != 1){
				logger.warn("more than one or no structure data found!");
			}
			for (StructureData entity : all) {
				return entity;
			}
		}
		throw new EntityLoadException("no structure data found for uuid "+uuid);
	}

	public Collection<StructureData> loadAllStructureData() throws EntityLoadException {
		Collection<StructureData> result = new ArrayList<StructureData>();
		//check if directory is set
		Object importDirectoryObj = loadParameters.get(PROPERTY_KEY_IMPORT_DIRECTORY);
		if (importDirectoryObj instanceof File) {
			File importDir = (File) importDirectoryObj;
			//really is directory, get all files and compare extensions to known
			Collection<IUUIDHeader> loaded = loadAllByClass(importDir, StructureData.class,importedStructureFiles);
			for (IUUIDHeader iuuidHeader : loaded) {
				if (iuuidHeader instanceof StructureData) {
					StructureData entiy = (StructureData) iuuidHeader;
					result.add(entiy);
				}
			}
		}else{
			throw new EntityLoadException(PROPERTY_KEY_IMPORT_DIRECTORY+ " not set correctly, cannot import all structures from there");
		}
		return result;
	}

	protected StructureData importStructureFromFile(File file) throws EntityLoadException{
		IUUIDHeader entity = persister.importEntityFromXML(file, StructureData.class);
		if (entity instanceof StructureData) {
			StructureData structure = (StructureData) entity;
			importedStructureFiles.put(structure.getUuid(),file); //only if import was successful
			return structure;
		}
		throw new EntityLoadException("Wrong entity type loaded: "+(entity != null?entity.getClass():null)+
				", expected: "+StructureData.class.getSimpleName());
	}

	public void tidyUpStructures(List<UUID> uuids){
		File archiveDir = null;
		Object obj = loadParameters.get(PROPERTY_KEY_ARCHIVE_DIRECTORY);
		if (obj instanceof File) {
			archiveDir = (File) obj;
		}
		for (UUID uuid : uuids) {
			File file = importedStructureFiles.get(uuid);
			if(file != null){
				if(archiveDir == null){
					//assume no archiving desired, so delete files from import folder
					file.delete();
				}else{
					//move files to archive
					//prepare archive directory
					File moveToDir = prepareArchiveDir(archiveDir,archiveDirNameStructure);
					try {
						CBFFileUtil.copyFileToDir(file, moveToDir,TIME_FORMAT.format(new Date()));
						//delete original import file for move
						file.delete();
					} catch (IOException e) {
						logger.error(e);
					}
				}
			}else{
				logger.error("desired uuid not found in imported structure files");
			}
		}
	}

	@Override
	public void saveStructure(StructureData entity) throws EntitySaveException {
		saveEntity(entity);
	}

	/**
	 * returned dir is archivedir+currentdate+archivedirname
	 * @param archiveDir
	 * @param archiveDirName
	 * @return
	 */
	protected File prepareArchiveDir(File archiveDir, String archiveDirName) {
		Date currentTime = new Date(System.currentTimeMillis());
		String dateDirName = DATE_FORMAT.format(currentTime);
		String archiveDirPath = archiveDir.getAbsolutePath()+"/"+dateDirName+"/"+archiveDirName+"/";
		File result = new File(archiveDirPath);
		result.mkdirs();
		return result;
	}

	protected void saveEntity(IUUIDHeader entity) throws EntitySaveException{
		Object exportFileObj = saveParameters.get(PROPERTY_KEY_EXPORT_FILE);
		if (exportFileObj instanceof File) {
			File file = (File) exportFileObj;
			String exportPath = persister.exportEntityToXML(file, entity);
			logger.debug("Entity exported to: "+exportPath);
			return;
		}
		Object exportDirectoryObj = saveParameters.get(PROPERTY_KEY_EXPORT_DIRECTORY);
		if (exportDirectoryObj instanceof File) {
			File file = (File) exportDirectoryObj;
			String exportPath = persister.exportEntityToXML(file.getAbsolutePath()+"/", entity, true,uuidFilenameMode);//somehow looses end / so would save wrong names
			logger.debug("Entity exported to: "+exportPath);
			return;
		}
		logger.error("Export file and directory are not set here");
	}

	protected Collection<IUUIDHeader> loadAllByClass(File directory,Class<? extends UUIDHeader> clazz,Map<UUID, File> importedMap) throws EntityLoadException{
		Collection<IUUIDHeader> result = new ArrayList<IUUIDHeader>();
		//obtain extension
		File[] files = getFilteredFilesFromDirectory(directory,clazz);
        for (int i = 0; i < files.length; i++) {
        	File file = files[i];
        	try{
        		IUUIDHeader entity = persister.importEntityFromXML(file, clazz);
            	result.add(entity);
            	importedMap.put(entity.getUuid(), file);
        	}catch (EntityLoadException e) {
        		logger.error("entity not loaded from file: "+file);
			}

		}
        return result;
	}

	protected File[] getFilteredFilesFromDirectory(File directory,Class<? extends UUIDHeader> clazz){
		final String extension = persister.getExtensionForClass(clazz);
		FilenameFilter filter = new FilenameFilter() {
            public boolean accept(java.io.File dir, String name) {
                return name.contains(extension);
            }
        };
        //get all files in directory with extension
        File[] files = directory.listFiles(filter);
        return files;
	}

	protected IUUIDHeader loadEntityFromDirectoryByUUID(final UUID uuid,
			File directory,Class<? extends UUIDHeader> clazz,Map<UUID,File> importedFilesMap) throws EntityLoadException{
		File[] files = null;
		if(uuidFilenameMode){
			FilenameFilter filter = new FilenameFilter() {
	            public boolean accept(java.io.File dir, String name) {
	                return name.contains(uuid.toString());
	            }
	        };
	        //get all files in directory with extension
	         files = directory.listFiles(filter);
	         if(files.length == 1){
	        	 IUUIDHeader entity = persister.importEntityFromXML(files[0]);
	        	 importedFilesMap.put(entity.getUuid(),files[0]);
	         }
		}else{
			files = getFilteredFilesFromDirectory(directory, clazz);
		}
        for (int i = 0; i < files.length; i++) {
        	File file = files[i];
        	IUUIDHeader entity = persister.importEntityFromXML(file);
        	if(entity.getUuid().toString().equals(uuid.toString())){
        		importedFilesMap.put(entity.getUuid(),file);
				return entity;
			}
        }
        throw new EntityLoadException("no "+clazz.getSimpleName()+" found for uuid "+uuid);
	}

}
